package me.android.library.common.service;

import android.annotation.SuppressLint;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.NetworkRequest;
import android.os.Build;

import androidx.annotation.NonNull;

import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import me.android.library.common.enums.ConnectivityMode;
import me.android.library.common.event.ConnectionModeChangedEvent;
import me.android.library.utils.android.NetworkUtil;
import me.android.library.utils.android.SystemServiceUtil;

@Slf4j
public class ConnectivityService extends AbstractService {
    private static class SingletonHolder {
        @SuppressLint("StaticFieldLeak")
        private static final ConnectivityService instance = new ConnectivityService();
    }

    public static ConnectivityService getInstance() {
        return SingletonHolder.instance;
    }

    private ConnectivityManager cm;
    private BroadcastReceiver receiver;

    @Getter
    boolean isConnectedToInternet;
    private ConnectivityManager.NetworkCallback networkCallback;

    private ConnectivityService() {
    }

    @SuppressLint("ObsoleteSdkInt")
    @Override
    public void init() {
        super.init();
        cm = SystemServiceUtil.getConnectivityManager();

        // 根据系统版本选择网络监听方式
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            registerNetworkCallback();
        } else {
            registerBroadcastReceiver();
        }
    }

    @SuppressLint("ObsoleteSdkInt")
    @Override
    public void dispose() {
        super.dispose();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            unregisterNetworkCallback();
        } else {
            unregisterBroadcastReceiver();
        }
    }

    /**
     * 注册 NetworkCallback（Android 7.0+）
     */
    @SuppressLint("NewApi")
    private void registerNetworkCallback() {
        networkCallback = new ConnectivityManager.NetworkCallback() {
            @Override
            public void onAvailable(@NonNull Network network) {
                checkConnectivity();
            }

            @Override
            public void onLost(@NonNull Network network) {
                checkConnectivity();
            }

            @Override
            public void onCapabilitiesChanged(@NonNull Network network,
                                              @NonNull NetworkCapabilities capabilities) {
                checkConnectivity();
            }
        };

        NetworkRequest request = new NetworkRequest.Builder()
                .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
                .build();
        cm.registerNetworkCallback(request, networkCallback);
    }

    /**
     * 注销 NetworkCallback
     */
    @SuppressLint("NewApi")
    private void unregisterNetworkCallback() {
        if (networkCallback != null) {
            try {
                cm.unregisterNetworkCallback(networkCallback);
            } catch (Exception e) {
                log.warn("Failed to unregister network callback", e);
            }
        }
    }

    /**
     * 注册广播接收器（Android 7.0以下）
     */
    private void registerBroadcastReceiver() {
        receiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                checkConnectivity();
            }
        };
        getContext().registerReceiver(receiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
    }

    /**
     * 注销广播接收器
     */
    private void unregisterBroadcastReceiver() {
        if (receiver != null) {
            try {
                getContext().unregisterReceiver(receiver);
            } catch (Exception e) {
                log.warn("Failed to unregister broadcast receiver", e);
            }
        }
    }

    /**
     * 检查当前网络连接状态
     */
    @SuppressLint("ObsoleteSdkInt")
    public void checkConnectivity() {
        ConnectivityMode mode = ConnectivityMode.Broken;

        try {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                // 使用新API（Android 6.0+）
                Network network = cm.getActiveNetwork();
                if (network != null) {
                    NetworkCapabilities capabilities = cm.getNetworkCapabilities(network);
                    if (capabilities != null) {
                        // 1. 先判断是否具备互联网访问的基础能力
                        boolean hasInternetCapability = capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
                        // 2. 再判断是否通过系统验证（实际能联网，Android 10+ 推荐）
                        boolean isInternetValidated = capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
                        // 综合判定：具备基础能力且通过验证 → 可连接互联网
                        this.isConnectedToInternet = hasInternetCapability && isInternetValidated;
                        if (this.isConnectedToInternet) {
                            if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)) {
                                mode = ConnectivityMode.Ethernet;
                            } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
                                mode = ConnectivityMode.Wifi;
                                logWifiInfo();
                            } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
                                mode = ConnectivityMode.GSM;
                            } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_BLUETOOTH)) {
                                mode = ConnectivityMode.Bluetooth;
                            }
                        }
                    }
                }
            } else {
                // 使用旧API（Android 6.0以下）
                NetworkInfo netInfo = cm.getActiveNetworkInfo();
                if (netInfo != null && netInfo.isConnected()) {
                    switch (netInfo.getType()) {
                        case ConnectivityManager.TYPE_WIFI:
                            mode = ConnectivityMode.Wifi;
                            logWifiInfo();
                            break;
                        case ConnectivityManager.TYPE_MOBILE:
                            mode = ConnectivityMode.GSM;
                            break;
                        case ConnectivityManager.TYPE_ETHERNET:
                            mode = ConnectivityMode.Ethernet;
                            break;
                        case ConnectivityManager.TYPE_BLUETOOTH:
                            mode = ConnectivityMode.Bluetooth;
                            break;
                    }
                }
            }
        } catch (Exception e) {
            log.warn("Failed to check connectivity", e);
        } finally {
            postEvent(new ConnectionModeChangedEvent(mode));
        }
    }

    /**
     * 记录Wi-Fi连接信息（IP地址、网关）
     */
    private void logWifiInfo() {
        if (NetworkUtil.isConnectedToWiFi()) {
            String localIP = NetworkUtil.getLocalIPv4Address();
            String gateIP = NetworkUtil.getWifiGatewayIp();
            log.info("[wifi] Gate:{} Local:{}", gateIP, localIP);
        }
    }
}
